package com.ecarx.module_log.controller;

import android.os.Environment;
import android.os.StatFs;
import android.util.Log;

import com.ecarx.library_base.BaseApplication;
import com.ecarx.library_base.base_util.ThreadUtils;
import com.ecarx.module_log.R;
import com.ecarx.module_log.bean.FileBean;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.Timer;
import java.util.TimerTask;
import java.util.stream.Collectors;

import ecarx.jni.recorder.RecorderListener;
import ecarx.jni.recorder.ScreenRecorder;


/**
 * 录屏文件限制覆写
 */
public class RecordLimitController {
    public static final String TAG = "RecordLimitController";
    private static final float MAX_ROM = 100; //剩余空间小于100MB时，执行删除

    private boolean mIsRecording = false;

    private Timer timer;

    private List<FileBean> mRecordFile = new ArrayList<>();

    private ScreenRecorder mScreenRecorder = new ScreenRecorder();

    private String mRecordingName = "";  //正在录制中的文件名

    /**
     * 获取data目录可用大小
     *
     * @return （MB）
     */
    private long getAvailableRom() {
        File path = Environment.getDataDirectory();

        StatFs stat = new StatFs(path.getPath());
        long blockSize = stat.getBlockSizeLong();
        long availableBlocks = stat.getAvailableBlocksLong();
        long availableRom = blockSize * availableBlocks / 1048576;
        Log.d(TAG, "Available path=" + path.getAbsolutePath() + " blockSize : " + blockSize + ";   availableBlocks : " + availableBlocks + ";     " + "result : " + availableRom + "MB;");
        return availableRom;//返回M
    }

    /**
     * 执行限制逻辑
     *
     * @param maxLimit 最大文件数限制
     */
    public void startRecordLimit(int maxLimit, LimitListener listener) {
        if (timer != null) {
            timer.cancel();
            timer = null;
        }
        int deleteFileNum = needDeleteFileNum(maxLimit);
        if (deleteFileNum > 0) {
            deleteLastFile(deleteFileNum, listener);
        }
        start(listener);
    }


    public void startRecord(String maxTime, String maxnum, RecordLimitController.LimitListener listener) {
        mRecordFile.clear();
        ThreadUtils.getCachedPool().execute(() -> {
            if (beginCheckAndDelete(listener)) {
                mScreenRecorder.start(getSavePath() + File.separator, Integer.parseInt(maxTime), new RecorderListener() {
                    @Override
                    public void onStart(String fileName) {
                        File f = new File(fileName);
                        Log.d(TAG, "onStart: FileName=" + fileName);
                        mRecordingName = f.getName();
                        mRecordFile.add(new FileBean(false, f));
                        addFinishRecord(listener);
                        startRecordLimit(Integer.parseInt(maxnum), listener);
                    }

                    @Override
                    public void onError(int code) {
                        Log.d(TAG, "record onError errorCode: " + code);
                        clickStop();
                        ThreadUtils.runOnUiThread(() -> {
                            listener.recordError(BaseApplication.getInstance().getString(isOverMinSpace() ? R.string.no_space_stop_record : R.string.record_fail_msg));
                            listener.fileAdd(mRecordFile);
                        });
                    }
                });

            }
        });
    }

    /**
     * 删除排序最后的文件
     */
    public void deleteLastFile(int deleteFileNum, LimitListener listener) {
        File file = new File(getSavePath());
        List<File> recordMp4Files = getRecordMp4Files(file);
        if (recordMp4Files.size() > 0) {
            List<String> fileNames = new ArrayList<>();
            recordMp4Files.stream().sorted(Comparator.comparing(File::lastModified)).limit(deleteFileNum).forEach(file1 -> {
                Log.d(TAG, "deleteLastFile: " + file1.getName());
                boolean success = file1.delete();
                if (success) {
                    fileNames.add(file1.getName());
                }
            });
            if (listener != null) {
                listener.deleteFileList(fileNames);

            }

        }
    }

    private void addFinishRecord(RecordLimitController.LimitListener listener) {
        if (mRecordFile.size() > 1) {
            File file = mRecordFile.get(0).getFile();
            if (file.isFile() && file.exists()) {
                List<FileBean> fileBeans = Collections.singletonList(mRecordFile.get(0));
                Log.d(TAG, "addFinishRecord: fileBean=" + mRecordFile.get(0).toString());
                mRecordFile.remove(0);
                ThreadUtils.runOnUiThread(() -> listener.fileAdd(fileBeans));
            }
        }
    }

    /**
     * 开始检查内存空间是否已满，满就批量删除之前的文件
     *
     * @param listener
     * @return false 可以继续录制 ，true 空间小于100M，无法继续录制
     */
    public boolean beginCheckAndDelete(RecordLimitController.LimitListener listener) {
        if (isOverMinSpace()) {
            if (deleteOverFiles(listener)) return true;
            ThreadUtils.runOnUiThread(() -> listener.startOverMax());
            return false;
        } else {
            return true;
        }
    }

    /**
     * 超过100M批量删除文件
     *
     * @param listener
     * @return 批量删除文件后是否可以继续录制 true 可以继续录制 false无空间录制
     */
    private boolean deleteOverFiles(LimitListener listener) {
        File file = new File(getSavePath());
        List<File> recordMp4Files = getRecordMp4Files(file);
        List<String> fileNames = new ArrayList<>();
        boolean canRecord = false;
        for (File f : recordMp4Files) {
            if (f.exists() && f.isFile()) {
                f.delete();
                fileNames.add(f.getName());
                if (!isOverMinSpace()) {
                    canRecord = true;
                    break;
                }
            }
        }
        if (fileNames.size() > 0) {
            listener.deleteFileList(fileNames);
        }
        if (canRecord) {
            return true;
        }
        return false;
    }

    /**
     * 判断是否需要删除
     *
     * @param maxLimit 数量限制
     * @return
     */
    private int needDeleteFileNum(int maxLimit) {
        File file = new File(getSavePath());
        int size = getRecordMp4Files(file).size();
        if (isOverMinSpace()) {
            return 1;
        } else if (maxLimit != 0 && size >= maxLimit) {
            return size - maxLimit + 1;
        }
        return 0;
    }

    private List<File> getRecordMp4Files(File file) {
        if (file.listFiles() == null) {
            return Collections.EMPTY_LIST;
        }
        List<File> files = Arrays.asList(Objects.requireNonNull(file.listFiles()));
        return files.stream().filter(file1 -> file1.getName().endsWith(".mp4") && !file1.getName().equals(mRecordingName)).sorted(Comparator.comparing(File::lastModified)).collect(Collectors.toList());
    }


    public String getSavePath() {
        String path = BaseApplication.getInstance().getDataDir().getPath() + File.separator + "screenRecord";
        File dir = new File(path);
        if (!dir.exists()) {
            boolean mkdirs = dir.mkdirs();
            Log.d(TAG, "getSavePath.mkdirs=" + mkdirs);
        }
        return path;
    }

    public void stopRecording() {
        mIsRecording = false;
        if (timer != null) {
            timer.cancel();
            timer = null;
        }
        mRecordingName = "";
    }

    public boolean isRecording() {
        return mIsRecording;
    }

    public void clickStop() {
        stopRecording();
        mScreenRecorder.stop();
    }

    /**
     * 每秒判断一次是否超过剩余空间大小
     */
    private void start(LimitListener listener) {
        mIsRecording = true;
        timer = new Timer();
        TimerTask task = new TimerTask() {
            @Override
            public void run() {
                if (mIsRecording && isOverMinSpace()) {
                    File file = new File(getSavePath());
                    int size = getRecordMp4Files(file).size();
                    if (size <= 0) {
                        stopRecordAndChangeUI(listener);
                    } else if (!deleteOverFiles(listener)) {
                        stopRecordAndChangeUI(listener);
                    }
                }
            }
        };
        timer.schedule(task, 500, 1000);
    }

    private void stopRecordAndChangeUI(LimitListener listener) {
        clickStop();
        ThreadUtils.runOnUiThread(() -> {
            listener.recordError(BaseApplication.getInstance().getString(R.string.no_space_stop_record));
            listener.fileAdd(mRecordFile);
        });
    }

    public List<FileBean> getRecordFile() {
        return mRecordFile;
    }

    public boolean isOverMinSpace() {
        if (getAvailableRom() < MAX_ROM) {
            return true;
        } else {
            return false;
        }
    }


    public void clearShowFile() {
        mRecordFile.clear();
    }

    public interface LimitListener {

        void deleteFileList(List<String> fileName);  //删除最先的文件列表

        void recordError(String errorMsg);  //录制出错

        void fileAdd(List<FileBean> fileBeans);  //录制结束生成的文件

        void startOverMax();  //开始判断磁盘空间已满
    }
}
